﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

using Xc.DataAccess.Core;
using Xc.DataAccess.HyperTerminalCore.Models;

namespace Xc.DataAccess.HyperTerminalCore.Services
{
    /// <summary>
    /// UDP服务端信息
    /// </summary>
    public class UdpServerService :ViewModelBase, IUdpServerService
    {
        /// <summary>
        /// 配置信息
        /// </summary>
        public UdpServerOption Option { get; set; }
        UdpClient udpClient = new UdpClient();
        public async Task<Result> OpenAsync(UdpServerOption option)
        {
            Option = option;
            Close();
            Token = new CancellationTokenSource();
            if (Option == null)
            {
                return Result.Reject("请先指定配置信息");
            }
            return await Task.Run(() =>
            {
                try
                {
                    udpClient = new UdpClient(option.Port, AddressFamily.InterNetwork);
                    BeiginReceive(udpClient);
                    DealData();
                    return Result.Accept("建立连接成功");
                }
                catch (Exception err)
                {
                    return Result.Reject(err.Message);
                }

            });
        }
        private  void BeiginReceive(object state)
        {
            Task.Run(async() =>
            {
                while (!Token.IsCancellationRequested)
                {
                    var res = await udpClient.ReceiveAsync();
                    if (res.Buffer != null && res.Buffer.Length > 0)
                    {
                        ReceiveQueue.Enqueue(res);
                    }
                }
            });

        }
        private void DealData()
        {
            Task.Run(async () => 
            {
                while (!Token.IsCancellationRequested)
                {
                    if (ReceiveQueue.TryDequeue(out var receiveResult))
                    {
                         var client=  UdpClientOnlineInfos.Where(p => p.Address == receiveResult.RemoteEndPoint?.ToString()).FirstOrDefault(); 
                        if (client == null)
                        {
                            var info = new UdpClientOnlineInfo(receiveResult.RemoteEndPoint, udpClient, Option.Encoding);
                            if (Option.Dispatcher!=null)
                            {
                                Option.Dispatcher.Invoke(() =>
                                { 
                                    UdpClientOnlineInfos.Add(info); 
                                });
                            }
                            else
                            {
                                UdpClientOnlineInfos.Add(info);
                            }

                            ClientOnlineEvent?.Invoke(info);
                            ReceiveQueue.Enqueue(receiveResult);
                            continue;
                        }
                        client.UpdateDateTime = DateTime.Now;
                        client.ReceiveData(receiveResult.Buffer);
                    }
                    else
                    {
                       var cleints=  UdpClientOnlineInfos.Where(p => p.ActiveTimeSpan >= Option.TimeOut);
                       if (cleints.Any())
                        {
                            var cl = cleints.FirstOrDefault();
                            if (Option.Dispatcher != null)
                            {
                                Option.Dispatcher.Invoke(() =>
                                {
                                    while (cleints.Count()>0)
                                    {
                                        UdpClientOnlineInfos.Remove(cl);
                                    }
                                });
                            }
                            else
                            {
                                while (cleints.Count() > 0)
                                {
                                    UdpClientOnlineInfos.Remove(cl);
                                }
                            }
                            ClientOfflineEvent?.Invoke(cl);

                        }
                       await Task.Delay(10);
                    }
                }
            });
        }
        /// <summary>
        /// 客户端上线事件
        /// </summary>
        public event Action<UdpClientOnlineInfo> ClientOnlineEvent;
        /// <summary>
        /// 设备下限事件
        /// </summary>
        public event Action<UdpClientOnlineInfo> ClientOfflineEvent;
        ObservableCollection<UdpClientOnlineInfo> udpClientOnlineInfos = new ObservableCollection<UdpClientOnlineInfo>();
        /// <summary>
        /// 客户端在线泪飙
        /// </summary>
        public ObservableCollection<UdpClientOnlineInfo> UdpClientOnlineInfos
        {
            get => udpClientOnlineInfos;
            set
            {
                if (udpClientOnlineInfos == value)
                {
                    return;
                }

                udpClientOnlineInfos = value;
                RaisedPropertyChanged();
            }
        }
        public Queue<UdpReceiveResult> ReceiveQueue { get; set; }=new Queue<UdpReceiveResult>();
        CancellationTokenSource Token = new CancellationTokenSource();
        /// <summary>
        /// 关闭连接
        /// </summary>
        /// <returns></returns>
        public Result Close()
        {
            Token.Cancel();
            udpClient?.Close();
            udpClient?.Dispose();
            return Result.Accept("关闭成功");
        }
    }
}
